Oddiy tiplardan tashqariga chiqing. Ishonchli va tip-xavfsiz API'lar yaratish uchun TypeScript'ning shartli tiplar, shablon literallari va satr manipulyatsiyasi kabi ilg'or xususiyatlarini o'zlashtiring. Global dasturchilar uchun to'liq qo'llanma.
TypeScript'ning To'liq Imkoniyatlarini Ochish: Shartli Tiplar, Shablon Literallari va Murakkab Satr Manipulyatsiyasiga Chuqur Kirish
Zamonaviy dasturiy ta'minot ishlab chiqish dunyosida TypeScript JavaScript uchun oddiy tip-tekshiruvchi sifatidagi dastlabki rolidan ancha uzoqqa chiqdi. U tip darajasida dasturlash deb ta'riflanishi mumkin bo'lgan murakkab vositaga aylandi. Ushbu paradigma dasturchilarga tiplarning o'zi ustida ishlaydigan kod yozish imkonini beradi, dinamik, o'z-o'zini hujjatlashtiradigan va ajoyib darajada xavfsiz API'lar yaratadi. Ushbu inqilobning markazida birgalikda ishlaydigan uchta kuchli xususiyat yotadi: Shartli Tiplar, Shablon Literal Tiplari va bir qator ichki Satr Manipulyatsiyasi Tiplari.
TypeScript ko'nikmalarini oshirishni istagan butun dunyodagi dasturchilar uchun ushbu tushunchalarni anglash endi hashamat emas, balki kengaytiriladigan va qo'llab-quvvatlanadigan ilovalarni yaratish uchun zaruratdir. Ushbu qo'llanma sizni asosiy tamoyillardan boshlab, ularning birgalikdagi kuchini namoyish etuvchi murakkab, real hayotiy patternlargacha bo'lgan chuqur sayohatga olib boradi. Dizayn tizimi, tip-xavfsiz API mijozi yoki murakkab ma'lumotlarni qayta ishlash kutubxonasini yaratayotgan bo'lsangiz ham, ushbu xususiyatlarni o'zlashtirish TypeScript yozish uslubingizni tubdan o'zgartiradi.
Asos: Shartli Tiplar (`extends` Ternar operatori)
O'z mohiyatiga ko'ra, shartli tip sizga tip munosabatini tekshirish asosida ikki mumkin bo'lgan tipdan birini tanlash imkonini beradi. Agar siz JavaScript'ning ternar operatori (shart ? rostQiymat : yolg'onQiymat) bilan tanish bo'lsangiz, sintaksisni darhol tushunasiz:
type Result = SomeType extends OtherType ? TrueType : FalseType;
Bu yerda extends kalit so'zi bizning shartimiz vazifasini bajaradi. U SomeType tipini OtherType tipiga tayinlash mumkinligini tekshiradi. Keling, buni oddiy misol bilan tahlil qilamiz.
Asosiy Misol: Tipni Tekshirish
Tasavvur qiling, biz berilgan T tipi satr bo'lsa true, aks holda false ga aylanadigan tip yaratmoqchimiz.
type IsString
Keyin biz bu tipni quyidagicha ishlatishimiz mumkin:
type A = IsString<"hello">; // A tipi true bo'ladi
type B = IsString<123>; // B tipi false bo'ladi
Bu asosiy qurilish blokidir. Ammo shartli tiplarning haqiqiy kuchi infer kalit so'zi bilan birgalikda ochiladi.
`infer`ning Kuchi: Ichkaridan Tiplarni Chiqarib Olish
infer kalit so'zi o'yin qoidalarini o'zgartiradi. U sizga extends bandi ichida yangi generik tip o'zgaruvchisini e'lon qilishga imkon beradi va siz tekshirayotgan tipning bir qismini samarali tarzda ushlab qoladi. Buni qiymatini pattern bo'yicha moslashtirishdan oladigan tip darajasidagi o'zgaruvchini e'lon qilish deb o'ylang.
Klassik misol - Promise ichidagi tipni "yechish".
type UnwrapPromise
Keling, buni tahlil qilamiz:
T extends Promise: BuTningPromiseekanligini tekshiradi. Agar shunday bo'lsa, TypeScript strukturani moslashtirishga harakat qiladi.infer U: Agar mos kelish muvaffaqiyatli bo'lsa, TypeScriptPromiseqaytaradigan tipni ushlab, uniUnomli yangi tip o'zgaruvchisiga joylashtiradi.? U : T: Agar shart rost bo'lsa (TPromiseedi), natijaviy tipU(yechilgan tip) bo'ladi. Aks holda, natijaviy tip shunchaki aslTtipidir.
Qo'llanilishi:
type User = { id: number; name: string; };
type UserPromise = Promise
type UnwrappedUser = UnwrapPromise
type UnwrappedNumber = UnwrapPromise
Ushbu pattern shunchalik keng tarqalganki, TypeScript'da ReturnType kabi o'rnatilgan yordamchi tiplar mavjud bo'lib, u funksiyaning qaytariladigan tipini chiqarib olish uchun xuddi shu tamoyildan foydalanadi.
Distributiv Shartli Tiplar: Unionlar (Birlashmalar) bilan Ishlash
Shartli tiplarning qiziqarli va muhim xususiyati shundaki, tekshirilayotgan tip "o'ralmagan" generik tip parametri bo'lganda ular distributiv bo'lib qoladi. Bu shuni anglatadiki, agar siz unga union tipini uzatsangiz, shart unionning har bir a'zosiga alohida qo'llaniladi va natijalar yangi unionga qayta yig'iladi.
Tipni shu tipning massiviga aylantiradigan tipni ko'rib chiqing:
type ToArray
Agar biz ToArray ga union tipini uzatsak:
type StrOrNumArray = ToArray
Natija (string | number)[] emas. T o'ralmagan tip parametri bo'lgani uchun, shart taqsimlanadi:
ToArraystring[]ga aylanadiToArraynumber[]ga aylanadi
Yakuniy natija ushbu individual natijalarning birlashmasi: string[] | number[].
Ushbu distributiv xususiyat unionlarni filtrlash uchun juda foydalidir. Masalan, o'rnatilgan Extract yordamchi tipi T unionidan U ga tayinlanishi mumkin bo'lgan a'zolarni tanlash uchun bundan foydalanadi.
Agar siz ushbu distributiv xususiyatni oldini olishingiz kerak bo'lsa, tip parametrini extends bandining har ikki tomonida kortaj (tuple) ichiga o'rashingiz mumkin:
type ToArrayNonDistributive
type StrOrNumArrayUnified = ToArrayNonDistributive
Ushbu mustahkam poydevor bilan, keling, dinamik satr tiplarini qanday qurishimiz mumkinligini o'rganamiz.
Tip Darajasida Dinamik Satrlarni Yaratish: Shablon Literal Tiplari
TypeScript 4.1 da taqdim etilgan Shablon Literal Tiplari sizga JavaScript'ning shablon literal satrlariga o'xshash shakldagi tiplarni aniqlash imkonini beradi. Ular mavjud satr literal tiplaridan yangilarini birlashtirish, qo'shish va yaratishga imkon beradi.
Sintaksis siz kutgandek:
type World = "World";
type Greeting = `Hello, ${World}!`; // Greeting tipi "Hello, World!" bo'ladi
Bu oddiy tuyulishi mumkin, ammo uning kuchi unionlar va generiklar bilan birlashganda namoyon bo'ladi.
Unionlar va Permutatsiyalar
Shablon literal tipi unionni o'z ichiga olganda, u har bir mumkin bo'lgan satr permutatsiyasini o'z ichiga olgan yangi unionga kengayadi. Bu aniq belgilangan konstantalar to'plamini yaratishning kuchli usulidir.
CSS margin xususiyatlari to'plamini aniqlashni tasavvur qiling:
type Side = "top" | "right" | "bottom" | "left";
type MarginProperty = `margin-${Side}`;
MarginProperty uchun natijaviy tip:
"margin-top" | "margin-right" | "margin-bottom" | "margin-left"
Bu faqat ma'lum satr formatlariga ruxsat berilgan tip-xavfsiz komponent proplari yoki funksiya argumentlarini yaratish uchun mukammaldir.
Generiklar bilan Birlashtirish
Shablon literallari generiklar bilan ishlatilganda haqiqatan ham porlaydi. Siz qandaydir kiritilgan ma'lumotlarga asoslangan holda yangi satr literal tiplarini yaratadigan fabrika tiplarini yaratishingiz mumkin.
type MakeEventListener
type UserListener = MakeEventListener<"user">; // "onUserChange"
type ProductListener = MakeEventListener<"product">; // "onProductChange"
Ushbu pattern dinamik, tip-xavfsiz API'larni yaratishning kalitidir. Ammo agar biz satrning registri (case)ni o'zgartirishimiz kerak bo'lsa, masalan, "onUserChange" ni olish uchun "user" ni "User" ga o'zgartirish kerak bo'lsa-chi? Aynan shu yerda satr manipulyatsiyasi tiplari yordamga keladi.
Asboblar To'plami: Ichki Satr Manipulyatsiyasi Tiplari
Shablon literallarini yanada kuchliroq qilish uchun TypeScript satr literallarini manipulyatsiya qilish uchun bir qator o'rnatilgan tiplarni taqdim etadi. Bular yordamchi funksiyalarga o'xshaydi, lekin tip tizimi uchun.
Registr O'zgartiruvchilar: `Uppercase`, `Lowercase`, `Capitalize`, `Uncapitalize`
Bu to'rtta tip o'z nomlariga mos ishni bajaradi:
Uppercase: Butun satr tipini yuqori registrga o'tkazadi.type LOUD = Uppercase<"hello">; // "HELLO"Lowercase: Butun satr tipini quyi registrga o'tkazadi.type quiet = Lowercase<"WORLD">; // "world"Capitalize: Satr tipining birinchi belgisini yuqori registrga o'tkazadi.type Proper = Capitalize<"john">; // "John"Uncapitalize: Satr tipining birinchi belgisini quyi registrga o'tkazadi.type variable = Uncapitalize<"PersonName">; // "personName"
Keling, avvalgi misolimizga qaytaylik va an'anaviy hodisa ishlovchisi nomlarini yaratish uchun Capitalize yordamida uni yaxshilaymiz:
type MakeEventListener
type UserListener = MakeEventListener<"user">; // "onUserChange"
type ProductListener = MakeEventListener<"product">; // "onProductChange"
Endi bizda barcha qismlar mavjud. Keling, ular murakkab, real hayotiy muammolarni hal qilish uchun qanday birlashishini ko'rib chiqamiz.
Sintez: Ilg'or Patternlar uchun Uchalasini Birlashtirish
Bu nazariyaning amaliyot bilan uchrashadigan joyi. Shartli tiplar, shablon literallari va satr manipulyatsiyasini bir-biriga bog'lab, biz nihoyatda murakkab va xavfsiz tip ta'riflarini yaratishimiz mumkin.
1-Pattern: To'liq Tip-Xavfsiz Hodisa Tarqatuvchi (Event Emitter)
Maqsad: on(), off(), va emit() kabi to'liq tip-xavfsiz metodlarga ega bo'lgan generik EventEmitter klassini yaratish. Bu quyidagilarni anglatadi:
- Metodlarga uzatilgan hodisa nomi haqiqiy hodisa bo'lishi kerak.
emit()ga uzatilgan ma'lumot (payload) ushbu hodisa uchun belgilangan tipga mos kelishi kerak.on()ga uzatilgan qayta chaqiruv (callback) funksiyasi ushbu hodisa uchun to'g'ri ma'lumot tipini qabul qilishi kerak.
Birinchidan, hodisa nomlarini ularning ma'lumot tiplariga bog'laydigan xaritani aniqlaymiz:
interface EventMap {
"user:created": { userId: number; name: string; };
"user:deleted": { userId: number; };
"product:added": { productId: string; price: number; };
}
Endi biz generik EventEmitter klassini yaratishimiz mumkin. Biz EventMap strukturasini kengaytirishi kerak bo'lgan Events generik parametrini ishlatamiz.
class TypedEventEmitter
private listeners: { [K in keyof Events]?: ((payload: Events[K]) => void)[] } = {};
// `on` metodi bizning Events xaritamizning kaliti bo'lgan generik `K` ni ishlatadi
on
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]?.push(callback);
}
// `emit` metodi ma'lumotning hodisa tipiga mos kelishini ta'minlaydi
emit
this.listeners[event]?.forEach(callback => callback(payload));
}
}
Keling, uni yaratamiz va ishlatamiz:
const appEvents = new TypedEventEmitter
// Bu tip-xavfsiz. Ma'lumot to'g'ri ravishda { userId: number; name: string; } deb aniqlanadi
appEvents.on("user:created", (payload) => {
console.log(`Foydalanuvchi yaratildi: ${payload.name} (ID: ${payload.userId})`);
});
// TypeScript bu yerda xatolik beradi, chunki "user:updated" EventMap da kalit emas
// appEvents.on("user:updated", () => {}); // Xato!
// TypeScript bu yerda xatolik beradi, chunki ma'lumotda 'name' xususiyati yo'q
// appEvents.emit("user:created", { userId: 123 }); // Xato!
Ushbu pattern an'anaviy ravishda ko'plab ilovalarning juda dinamik va xatoliklarga moyil qismi bo'lgan narsalar uchun kompilyatsiya vaqtidagi xavfsizlikni ta'minlaydi.
2-Pattern: Ichki Obyektlar uchun Tip-Xavfsiz Yo'l Orqali Kirish
Maqsad: Ichki T obyektidagi qiymat tipini nuqta-notatsiyali P satr yo'li (masalan, "user.address.city") yordamida aniqlay oladigan PathValue yordamchi tipini yaratish.
Bu rekursiv shartli tiplarni namoyish etuvchi juda ilg'or pattern.
Bu yerda uni amalga oshirish, biz buni tahlil qilamiz:
type PathValue
? Key extends keyof T
? PathValue
: never
: P extends keyof T
? T[P]
: never;
Keling, uning mantig'ini misol bilan kuzatamiz: PathValue
- Boshlang'ich chaqiruv:
P"a.b.c". Bu`${infer Key}.${infer Rest}`shablon literaliga mos keladi. Key"a"sifatida aniqlanadi.Rest"b.c"sifatida aniqlanadi.- Birinchi rekursiya: Tip
"a"ningMyObjectkaliti ekanligini tekshiradi. Agar ha bo'lsa, u rekursiv ravishdaPathValueni chaqiradi. - Ikkinchi rekursiya: Endi
P"b.c". U yana shablon literaliga mos keladi. Key"b"sifatida aniqlanadi.Rest"c"sifatida aniqlanadi.- Tip
"b"ningMyObject["a"]kaliti ekanligini tekshiradi va rekursiv ravishdaPathValueni chaqiradi. - Asosiy holat: Nihoyat,
P"c". Bu`${infer Key}.${infer Rest}`ga mos kelmaydi. Tip mantig'i ikkinchi shartga o'tadi:P extends keyof T ? T[P] : never. - Tip
"c"ningMyObject["a"]["b"]kaliti ekanligini tekshiradi. Agar ha bo'lsa, natijaMyObject["a"]["b"]["c"]bo'ladi. Agar yo'q bo'lsa, uneverbo'ladi.
Yordamchi funksiya bilan foydalanish:
declare function get
const myObject = {
user: {
name: "Alice",
address: {
city: "Wonderland",
zip: 12345
}
}
};
const city = get(myObject, "user.address.city"); // const city: string
const zip = get(myObject, "user.address.zip"); // const zip: number
const invalid = get(myObject, "user.email"); // const invalid: never
Ushbu kuchli tip yo'llardagi imlo xatolaridan kelib chiqadigan ish vaqtidagi xatoliklarning oldini oladi va murakkab API javoblari bilan ishlaydigan global ilovalarda keng tarqalgan muammo bo'lgan chuqur joylashgan ma'lumotlar tuzilmalari uchun mukammal tipni aniqlashni ta'minlaydi.
Eng Yaxshi Amaliyotlar va Ishlash Samaradorligi
Har qanday kuchli vosita kabi, bu xususiyatlardan oqilona foydalanish muhimdir.
- O'qish Osonligiga Ustuvorlik Bering: Murakkab tiplar tezda o'qib bo'lmaydigan holga kelishi mumkin. Ularni kichikroq, yaxshi nomlangan yordamchi tiplarga ajrating. Murakkab ish vaqti kodi bilan bo'lgani kabi, mantiqni tushuntirish uchun izohlardan foydalaning.
- `never` Tipini Tushunish:
nevertipi shartli tiplarda xato holatlarini boshqarish va unionlarni filtrlash uchun asosiy vositangizdir. U hech qachon yuz bermasligi kerak bo'lgan holatni ifodalaydi. - Rekursiya Cheklovlaridan Ogoh Bo'ling: TypeScript tipni yaratish uchun rekursiya chuqurligi chegarasiga ega. Agar tiplaringiz juda chuqur joylashgan yoki cheksiz rekursiv bo'lsa, kompilyator xatolik beradi. Rekursiv tiplaringiz aniq asosiy holatga ega ekanligiga ishonch hosil qiling.
- IDE Ishlash Samaradorligini Kuzatib Boring: O'ta murakkab tiplar ba'zan TypeScript til serverining ish faoliyatiga ta'sir qilishi mumkin, bu esa muharriringizda avtomatik to'ldirish va tip tekshiruvining sekinlashishiga olib keladi. Agar sekinlashuvni sezsangiz, murakkab tipni soddalashtirish yoki ajratish mumkinligini ko'rib chiqing.
- Qachon To'xtashni Biling: Bu xususiyatlar tip xavfsizligi va dasturchi tajribasining murakkab muammolarini hal qilish uchun mo'ljallangan. Ularni oddiy tiplarni ortiqcha muhandislik qilish uchun ishlatmang. Maqsad aniqlik va xavfsizlikni oshirish, keraksiz murakkablik qo'shish emas.
Xulosa
Shartli tiplar, shablon literallari va satr manipulyatsiyasi tiplari shunchaki alohida xususiyatlar emas; ular tip darajasida murakkab mantiqni bajarish uchun mahkam birlashtirilgan tizimdir. Ular bizga oddiy annotatsiyalardan tashqariga chiqishga va o'zlarining tuzilishi va cheklovlarini chuqur anglaydigan tizimlarni yaratishga imkon beradi.
Ushbu uchlikni o'zlashtirib, siz quyidagilarni amalga oshirishingiz mumkin:
- O'z-o'zini Hujjatlashtiradigan API'lar Yaratish: Tiplarning o'zi hujjatga aylanadi va dasturchilarni ulardan to'g'ri foydalanishga yo'naltiradi.
- Butun Bir Xatolar Sinfini Yo'qotish: Tip xatolari ishlab chiqarishda foydalanuvchilar tomonidan emas, balki kompilyatsiya vaqtida aniqlanadi.
- Dasturchi Tajribasini Yaxshilash: Kodingizning eng dinamik qismlari uchun ham boy avtomatik to'ldirish va ichki xato xabarlaridan bahramand bo'ling.
Ushbu ilg'or imkoniyatlarni qabul qilish TypeScript'ni xavfsizlik tarmog'idan ishlab chiqishdagi kuchli hamkorga aylantiradi. Bu sizga murakkab biznes mantig'i va invariantlarni to'g'ridan-to'g'ri tip tizimiga kiritish imkonini beradi, bu esa ilovalaringizning global auditoriya uchun yanada mustahkam, qo'llab-quvvatlanadigan va kengaytiriladigan bo'lishini ta'minlaydi.